/* Created by Richard Fleming
 * Copyright 2008 Johnson County Community College
 * Free for non-commercial use
 */

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace XnaUtility.GameObjects
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Base3DGameObject : Microsoft.Xna.Framework.DrawableGameComponent
    {

        public Vector3 location;
        public Vector3 rotation;
        public Vector3 velocity;
        public Vector3 scale;

        protected Model model;

        private string modelName;
        protected Game game;

        public bool alive = true;

        protected Camera.CameraBase camera;

        protected Matrix[] transforms;

        public Base3DGameObject(Game game, string modelName)
            : base(game)
        {
            this.modelName = modelName;
            this.game = game;
            scale = new Vector3(10.0f);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            InitObject();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            model = game.Content.Load<Model>(modelName);
            transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            base.LoadContent();

            camera = (Camera.CameraBase)game.Services.GetService(typeof(Camera.CameraBase));
        }

        public virtual void ForceLoadContent()
        {
            LoadContent();
        }

        public void SetCamera(Camera.CameraBase camera)
        {
            this.camera = camera;
        }

        public void InitObject()
        {
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
           
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {

            base.Draw(gameTime);
        }

        /// <summary>
        /// A very basic implementation of draw
        /// </summary>
        public void BasicDraw()
        {
            // Draw the model. A model can have multiple meshes, so loop.
            foreach (ModelMesh mesh in model.Meshes)
            {
                // This is where the mesh orientation is set, as well as our camera and projection.
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.World = transforms[mesh.ParentBone.Index]
                        * Matrix.CreateScale(scale)
                        * Matrix.CreateRotationY(rotation.Y)
                        * Matrix.CreateRotationX(rotation.X)
                        * Matrix.CreateRotationZ(rotation.Z)
                        * Matrix.CreateTranslation(location);
                    effect.View = camera.View;
                    effect.Projection = camera.Projection;
                }
                // Draw the mesh, using the effects set above.
                mesh.Draw();
            }
        }
    }
}